package class03_一些基础的数据结构.test;

import java.util.ArrayList;
import java.util.List;

public class Code01_ReverseList {
    public static class Node{
        public int value;
        public Node next;

        public Node(int value) {
            this.value = value;
        }
    }
    public static class DoubleNode{
        public int value;
        public DoubleNode last;
        public DoubleNode next;

        public DoubleNode(int i) {
            this.value = i;
        }
    }

    /**
     * 单链表的反转
     */
    public static Node reverseLinkedList(Node head){
        Node pre = null;
        Node next = null;
        while (head != null){
          next =  head.next;
          head.next = pre;
          pre = head;
          head = next;
        }
        return pre;
    }

    /**
     * 双链表的反转
     */
    public static DoubleNode reverseDoubleLinkedList(DoubleNode head){
        DoubleNode pre = null;
        DoubleNode next = null;
        while (head != null){
            next = head.next;
            head.next = pre;
            head.last = next;
            pre = head;
            head = next;
        }
        return pre;
    }

    /**
     * 利用数组处理单链表反转
     * @param head
     * @return
     */
    public static Node testReverseLinkedList(Node head){
        if(head == null){
            return head;
        }
        List<Node> handle = new ArrayList<>();
        while (head != null){
            handle.add(head);
            head = head.next;
        }
        handle.get(0).next = null;
        for (int i = 1; i <handle.size(); i++) {
            handle.get(i).next = handle.get(i - 1);
        }
        return handle.get(handle.size()-1);
    }
    /**
     * 利用数组处理双向链表反转
     */
    public static DoubleNode testReverseDoubleList(DoubleNode head){
        if(head == null){
            return head;
        }
        List<DoubleNode> handle = new ArrayList<>();
        while (head != null){
            handle.add(head);
            head = head.next;
        }
        for (int i = 0; i <=handle.size()-1; i++) {
            handle.get(i).next = i == 0 ? null : handle.get(i - 1);
            handle.get(i).last = i == (handle.size()-1) ? null : handle.get(i + 1);
        }
        return handle.get(handle.size()-1);
    }

    public static void main(String[] args) {
        int len = 50;
        int value = 100;
        int testTimes = 100000;
        System.out.println("开始测试");
        for (int i = 0; i < testTimes; i++) {
            Node node1 = generateRandomLinkedList(len, value);
            List<Integer> list1 = getLinkedListOriginOrder(node1);
            node1 = reverseLinkedList(node1);
            if(!checkLinkedListReverse(node1,list1)){
                System.out.println("Oops!");
            }
            Node node2 = generateRandomLinkedList(len,value);
            List<Integer> list2 = getLinkedListOriginOrder(node2);
            node2 = testReverseLinkedList(node2);
            if(!checkLinkedListReverse(node2,list2)){
                System.out.println("Oops!");
            }

            //双向链表测试
            DoubleNode node3 = generateRandomDoubleList(len,value);
            List<Integer> list3 = getDoubleListOriginOrder(node3);
            node3 = reverseDoubleLinkedList(node3);
            if(!checkDoubleListReverse(node3,list3)){
                System.out.println("Oops!!!");
            }


            DoubleNode node4 = generateRandomDoubleList(len,value);
            List<Integer> list4 = getDoubleListOriginOrder(node4);
            node4 = testReverseDoubleList(node4);
            if(!checkDoubleListReverse(node4,list4)){
                System.out.println("Oops!!!");
            }

        }
        System.out.println("结束测试");

    }

    private static boolean checkDoubleListReverse(DoubleNode head, List<Integer> list) {
        for (int i = list.size() - 1; i >= 0 ; i--) {
            if(list.get(i) != head.value){
                return false;
            }
            head = head.next;
        }
        return true;
    }

    private static List<Integer> getDoubleListOriginOrder(DoubleNode head) {
        List<Integer> res = new ArrayList<>();
        while (head != null){
            res.add(head.value);
            head = head.next;
        }
        return res;
    }

    private static DoubleNode generateRandomDoubleList(int len, int value) {
        int size = (int)(Math.random() * (1 + len));
        if(size == 0){
            return null;
        }
        DoubleNode head = new DoubleNode((int)(Math.random()*(1+value)));
        head.last = null;
        size--;
        DoubleNode pre = head;
        while (size > 0){
            DoubleNode cur = new DoubleNode((int)(Math.random() * (1 + value)));
            cur.last = pre;
            pre.next = cur;
            pre = cur;
            size--;
        }
        return head;
    }

    private static boolean checkLinkedListReverse(Node head, List<Integer> list) {
        for (int i = list.size() - 1; i >= 0; i--) {
            if(head.value != list.get(i)){
                return false;
            }
            head = head.next;
        }
        return true;
    }

    private static List<Integer> getLinkedListOriginOrder(Node head) {
        List<Integer> res = new ArrayList<>();
        while (head != null){
            res.add(head.value);
            head = head.next;
        }
        return res;
    }

    /**
     * 生成单链表
     * @param len
     * @param value
     * @return
     */
    private static Node generateRandomLinkedList(int len, int value) {
        int size = (int)(Math.random()*(len+1));
        if(size == 0){
            return null;
        }
        Node head = new Node((int)(Math.random()*(value + 1)));
        Node pre = head;
        for (int i = 1; i <= size; i++) {
            pre.next = new Node((int)(Math.random()*(value + 1)));
            pre = pre.next;
        }
        return head;
    }
}
